/*
 *	-------------------------------------------------------
 *  GSP295 Week1 - iLab (WFF Assignment)
 *  Author: Ronald
 *	
 *	-------------------------------------------------------
 *	DESCRIPTION: 
 *	-------------------------------------------------------
 *	The program takes a string input and determines if
 *	it has a WFF pattern by parsing the string.
 *
 *	The output is displayed on screen, as well as 
 *	stored to a TXT file
 *	-------------------------------------------------------
 */


#pragma region INCLUDES
#include <iostream>
#include <fstream>
#include <vector>

#include <string>
#include <stdio.h>
using namespace std;
#pragma endregion


#pragma region VARIALBES
bool Rule1(char const input);
bool Rule2(char const input);
bool Rule3(char const input);

bool WFF(string input);
string bool2String(bool input);
void Reset();

void fileExists(const char *filename);
void writeToFile (string input);


string input;
vector<char> output;
bool r1=false, r2=false, r3=false;
int R1=0, R2=0, R3=0;
#pragma endregion


int main()
{
	bool wffLocal = false, quit = false;
	char yesNo;
	string temp = "";


	cout << "\n===============================================" << endl;
	cout << "Welcome to GSP295 - Wk1 (WFF Assignment)" << endl;
	cout << "Author: Ronald Ram" << endl;
	cout << "===============================================" << endl << endl;

	
	//cout << '\n' << "Output: " << input << endl;
	//getline(cin, input, '\n');
	
	do {
		temp = input = "";
		cout << "\nEnter String : "; cin >> input;
		
		//Find WFF...
		wffLocal = WFF(input);

		
		//Output results to screen...
		cout << '\n' << "WFF Status: " << bool2String(wffLocal);
		if ( wffLocal ) //TRUE=1, FALSE=0
		{
			cout << "\tResult: ";
			for (int i=0; i< (int)output.size(); ++i) 
			{
				cout << output[i];
				temp += output[i];
			}
			cout << "\n";
		}
		else { cout << endl; }



		//check to see if file exists, otherwise create & write to file
		fileExists("output_RRam.txt");
		
		if ( wffLocal ) { temp += "\n-----------------------------------\n\n";
		} 
		else { temp = "\n-----------------------------------\n\n"; }

		writeToFile("Input: " + input + "\nResult: " + bool2String(wffLocal) + temp);
		
		Reset();
		cout << "\n===============================================" << endl << endl;

		

		cout << "TRY AGAIN (y/n): "; cin >> yesNo;
		if ( yesNo == 'n' ) { quit = true; }

	} while ( !quit );


	cout << "Good Bye!" << endl << endl;
	system("pause");

	return 0;
}


//Find WFF from input string
bool WFF (string input)
{
	bool WFF = false;
	bool exitLoop = false;


	if ( input.length() == 1 )
	{
		if ( Rule1(input [0]) )
		{
			output.push_back(input [0]);
			WFF = true;
		}
		else { WFF = false; }
	}
	else
	{
		for (int i = 0; i < (int) input.length(); ++i)
		{
			//figure which Rule to start testing...
			if ( Rule3(input [i]) && !r3 )
			{
				output.push_back(input [i]);
				r3 = true;
				++R3;
			}
			else if ( Rule2(input [i]) && !r2 )
			{
				output.push_back(input [i]);
				r2 = true;
				++R2;
			}
			else if ( Rule1(input [i]) && !r1 )
			{
				output.push_back(input [i]);
				r1 = true;
				++R1;
			}


			//Test for Rule:3
			if ( r3 )
			{
				for (int j = i + 1; j < (int) input.length(); ++j)
				{
					if ( Rule2(input [j]) )
					{
						output.push_back(input [j]);
						++R2;
					}
					else if ( Rule1(input [j]) )
					{
						output.push_back(input [j]);
						++R1;

						//check for WFF...
						if ( R3 == 1 && R2 == 2 & R1 == 1 )
						{
							WFF = true;
							exitLoop = true;
							break;
						}
						else if ( R3 == 1 && R2 == 1 & R1 == 1 )
						{
							WFF = true;
							exitLoop = true;
							break;
						}
						else if ( R3 == 1 && R1 == 2 )
						{
							WFF = true;
							exitLoop = true;
							break;
						}
					}
					else if ( Rule3(input [j]) )
					{
						Reset();
						WFF = false;
						break;
					}
				}//for-loop
			}


			//Test for Rule:2
			else if ( r2 )
			{
				for (int k = i + 1; k < (int) input.length(); ++k)
				{
					if ( Rule2(input [k]) )
					{
						output.push_back(input [k]);
						++R2;
					}
					else if ( Rule1(input [k]) )
					{
						output.push_back(input [k]);
						++R1;

						//check for WFF...
						if ( R2 == 2 & R1 == 1 )
						{
							WFF = true;
							exitLoop = true;
							break;
						}
						else if ( R2 == 1 && R1 == 1 )
						{
							WFF = true;
							exitLoop = true;
							break;
						}
					}
					else if ( Rule3(input [k]) )
					{
						Reset();
						WFF = false;
						break;
					}
				}//for-loop
			}


			//Test for Rule:1
			else if ( r1 )
			{
				Reset();
				WFF = false;
				continue;
			}

			//WFF Match Found, Break out of Loop
			if ( exitLoop ) { break; }
		}//outer: for-loop
	}

	//return the status of WFF check
	return WFF;
}


//Method to Check for Rule1 
bool Rule1(char const input)
{
	if (input == 'p') { return true; }
	else if (input == 'q') { return true; }
	else if (input == 'r') { return true; }
	else if (input == 's') { return true; }
	else { return false; }
}


//Method to Check for Rule2
bool Rule2(char const input)
{
	if (input == 'N') { return true; }
	else { return false; }
}


//Method to Check for Rule3
bool Rule3(char const input)
{
	if (input == 'C') { return true; }
	else if (input == 'A') { return true; }
	else if (input == 'K') { return true; }
	else if (input == 'E') { return true; }
	else { return false; }
}


//Reset all states, tracking data
void Reset()
{
	output.clear();
	r1 = r2 = r3 = false;
	R1 = R2 = R3 = 0;
}


//Method checks if out file exist, if not creates one
void fileExists(const char *filename)
{
	ifstream ifile(filename);
	if(!ifile)
	{
		ofstream outfile(filename);
		outfile.close();
	}
}


//Result of WFF appended to output file
void writeToFile(string input)
{
	string temp = input + '\n';
	FILE * file = fopen("output_RRam.txt", "a+");
		fputs(temp.c_str(), file);
		fclose(file);
}

//Friendly Msg for status of WFF
std::string bool2String( bool input )
{
	if ( input ) { return "SUCCESS, WFF MATCH FOUND!";
	} 
	else { return "------> NO WFF MATCH FOUND!"; }
}






